package cl.rizepe.playntest.core;

import java.util.HashMap;

import playn.core.Pointer.Event;
import playn.core.Pointer.Listener;
import cl.rizepe.playntest.core.effects.OnLayerEffect;
import cl.rizepe.playntest.core.views.EffectedLayer;

public class GestureManager implements Listener {
	 public  interface GestureManagerFactory{
		GestureManager createGestureManager(EffectedLayer layerState);
	}
	
	
	final public class ListenerLayerStateAdaptor implements Listener {
		Listener listener;
		EffectedLayer layerState=null;		
		
		@Override
		public void onPointerStart(Event event) {
			listener.onPointerStart(event);		
			
		}

		@Override
		public void onPointerEnd(Event event) {
			listener.onPointerEnd(event);						
		}

		@Override
		public void onPointerDrag(Event event) {
			listener.onPointerDrag(event);
		}

		public EffectedLayer getLayerState() {
			return layerState;
		}

		public void setLayerState(EffectedLayer layerState) {
			try{
				((OnLayerEffect) listener).setLayerState(layerState);
			}
			catch(Exception e){}
			finally{}
			
			this.layerState = layerState;
		}}
	
	
	public static enum Gesture{onClick,onDragStart,onDragMove,onDragEnd,onDoubleClick,onQuickDrag,onHold}
	private static enum Mode{Click,Drag,DoubleClick,QuickDrag,Hold,None}
	double startTime, endTime;
	double lastClick;
	HashMap<Gesture,Listener> gestures;
	Event startEvent,dragEvent,endEvent;
	Mode mode;
	
	
	public GestureManager (){
		gestures =new HashMap<Gesture,Listener>();	
		lastClick=0;
	}
	
	@Override
	public void onPointerStart(Event event) {
		startEvent=event;
		dragEvent=null;
		endEvent=null;
		startTime = startEvent.time();
		if (lastClick==0)
			lastClick=event.time();
		mode =Mode.None;
	}

	@Override
	public void onPointerDrag(Event event) {
		if (startEvent!=null)
			if (gestures.containsKey(Gesture.onDragStart)){
					mode = Mode.Drag;
		}
		double dt=event.time()-startTime;
		if (dt<500)
			mode=Mode.Click;
		switch (mode){
		case Drag:
			if (gestures.get(Gesture.onDragEnd)!=null){
				if (dragEvent==null)
					gestures.get(Gesture.onDragStart).onPointerStart(startEvent);		
				dragEvent=event;		
				gestures.get(Gesture.onDragMove).onPointerDrag(dragEvent);
			}	
			break;
		default:
			break;
		}
	}

	@Override
	public void onPointerEnd(Event event) {
		double clickTime=event.time()-startTime;
		double clicksTime=event.time()-lastClick;
		if ((lastClick!=0)&&(clicksTime<800)){
			mode=Mode.DoubleClick;
		}else{
			if (clickTime<500)
				mode=Mode.Click;
			if (dragEvent==null)
				mode=Mode.Click;
			}
		endEvent=event;
		switch (mode){
		case Drag:	
			if (gestures.get(Gesture.onDragEnd)!=null)
			gestures.get(Gesture.onDragEnd).onPointerEnd(endEvent);	
			break;
		case Click:
			if (gestures.get(Gesture.onClick)!=null)
				gestures.get(Gesture.onClick).onPointerEnd(endEvent);
			break;
		case DoubleClick:
			if (gestures.get(Gesture.onDoubleClick)!=null)
				gestures.get(Gesture.onDoubleClick).onPointerEnd(endEvent);
			break;
		default:
			break;
		}
		
		startEvent=null;
		dragEvent=null;
		endEvent=null;

		lastClick=event.time();
		mode=Mode.None;
	}

	public void addGestureListener(Gesture gesture, Listener listener){
		if (gestures.containsKey(gesture))
		{
			gestures.remove(gesture);
		}
		gestures.put(gesture,listener);
	}

	public void reasignLayerstate(EffectedLayer layerState) {
		/*por cada
		 * /*/
		for (Gesture gesture : gestures.keySet()){
			try{
				OnLayerEffect ole=(OnLayerEffect) gestures.get(gesture);
				ole.setLayerState(layerState);
			}
			catch(Exception e){
				//String s= e.toString();
			}
			finally{}
			
			
		}
		
	}
	
	
}
